package ay.shadow.security.config;

import ay.shadow.security.handler.CustomReactiveAuthManager;
import ay.shadow.security.handler.JwtAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import reactor.core.publisher.Mono;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final CustomReactiveAuthManager authManager;

    public SecurityConfig(JwtAuthenticationFilter customAuthFilter, CustomReactiveAuthManager authManager) {
        this.jwtAuthenticationFilter = customAuthFilter;
        this.authManager = authManager;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
                // 关闭CSRF保护（网关通常不需要）
                .csrf(csrf -> csrf.disable())
                // 关闭HTTP Basic认证
                .httpBasic(basic -> basic.disable())
                // 配置路径权限
                .authorizeExchange(exchanges -> exchanges
                        // 允许访问的公开路径
                        .pathMatchers("/", "/home", "/login", "/dashboard").permitAll()
                        // 允许访问登录API和登出API
                        .pathMatchers("/api/login", "/api/logout").permitAll()
                        // 其他所有请求需要认证
                        .anyExchange().authenticated()
                )
                // 配置自定义认证管理器
                .authenticationManager(authManager)
                // 禁用默认的安全上下文仓库（可选，根据需求）
                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
                // 添加自定义认证过滤器（在认证阶段之前执行）
                .addFilterAt(jwtAuthenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION)
                .exceptionHandling(ex -> ex
                        .authenticationEntryPoint((exchange, authException) -> {
                            exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.UNAUTHORIZED);
                            exchange.getResponse().getHeaders().setContentType(org.springframework.http.MediaType.APPLICATION_JSON);
                            return exchange.getResponse().writeWith(Mono.just(
                                    exchange.getResponse().bufferFactory().wrap(
                                            "{\"code\":401,\"msg\":\"未认证，请登录\"}".getBytes()
                                    )
                            ));
                        })
                )
                .build();
    }


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}